﻿package net.chrisjrock.text
{
	import flash.text.StyleSheet;
	import flash.text.TextFormat;
	
	/**
	 * ...
	 * @author Christopher J. Rock
	 */
	public class TextStyle
	{
		public static function parseToStyleSheet (styleSheetData:* , thoroughParsing:Boolean = false):StyleSheet {
			var styleSheet:StyleSheet = new StyleSheet();
			var style:*;
			for each (style in styleSheetData) {
				style = new TextStyle(style.name.toString() , style , thoroughParsing).getStyleObject();
				styleSheet.setStyle(style.name , style);
			}
			
			return styleSheet;
		}
		
		//Name of style within a stylesheet
		protected var _name:String;
		//Style properties within a stylesheet
		public var color:Object; //CSS:color; hex
		public var display:String; //CSS:display; inline, block, none
		public var fontFamily:String; //CSS:font-family; A comma-separated list of fonts to use, in descending order of desirability.
		public var fontSize:Object; //CSS:font-size; Pixels
		public var fontStyle:String; //CSS:font-style; normal, italic
		public var fontWeight:String; //CSS:font-weight; normal, bold
		public var kerning:Boolean; //CSS:kerning; Enabled/disabled.
		public var letterSpacing:Object; //CSS:letter-spacing; Pixels -- This style property is undocumented.
		public var leading:Object; //CSS:leading; Pixels -- Not Standard CSS, but recognized by Flash (though undocumented)
		public var marginLeft:Object; //CSS:margin-left; Pixels
		public var marginRight:Object; //CSS:margin-right; Pixels
		public var textAlign:String; //CSS:text-align; left, center, right, justify
		public var textDecoration:String; //CSS:text-decoration; none, underline
		public var textIndent:Object; //CSS:text-indent; Pixels
		//These three are not Standard CSS, but are recognized by Flash (though undocumented)
		public var blockIndent:Object; //CSS:block-indent; Pixels
		public var tabStops:Array; //CSS:tab-stops; An array of custom tab-stop locations as integers.
		public var bullet:Boolean; //CSS:bullet; Enabled/disabled.
		
		//TextFormat properties
		public var url:String;
		public var target:String;
		
		public static var NAME_A_LINK:String = "a:link";
		public static var NAME_A_HOVER:String = "a:hover";
		public static var NAME_A_ACTIVE:String = "a:active";
		public static var NAME_A_VISITED:String = "a:visited";
		
		public function TextStyle(name:String = null , styleObj:Object = null , thoroughParsing:Boolean = false) {
			this.name = name;
			resetToDefaults();
			if (styleObj) {
				if (styleObj is TextFormat) setToTextFormat(TextFormat(styleObj));
				else {
					if (thoroughParsing) parseStyleObject(styleObj);
					else setToStyleObject(styleObj);
				}
			}
		}
		
		public function resetToDefaults():TextStyle {
			color = 0;
			display = "inline";
			fontFamily = null;
			fontSize = 12;
			fontStyle = "normal";
			fontWeight = "normal";
			kerning = false;
			letterSpacing = 0;
			leading = 0;
			marginLeft = 0;
			marginRight = 0;
			textAlign = "left";
			textDecoration = "none";
			textIndent = 0;
			blockIndent = 0;
			tabStops = new Array();
			bullet = false;
			
			url = null;
			target = null;
			
			return this;
		}
		
		public function clone (name:String):TextStyle {
			var clonedStyle:TextStyle = new TextStyle(name);
			clonedStyle.color = color;
			clonedStyle.display = display;
			clonedStyle.fontFamily = fontFamily;
			clonedStyle.fontSize = fontSize;
			clonedStyle.fontStyle = fontStyle;
			clonedStyle.fontWeight = fontWeight;
			clonedStyle.kerning = kerning;
			clonedStyle.letterSpacing = letterSpacing;
			clonedStyle.leading = leading;
			clonedStyle.marginLeft = marginLeft;
			clonedStyle.marginRight = marginRight;
			clonedStyle.textAlign = textAlign;
			clonedStyle.textDecoration = textDecoration;
			clonedStyle.textIndent = textIndent;
			clonedStyle.blockIndent = blockIndent;
			clonedStyle.tabStops = tabStops ? tabStops.concat() : null;
			clonedStyle.bullet = bullet;
			clonedStyle.url = url;
			clonedStyle.target = target;
			
			return clonedStyle;
		}
		
		public function setToStyleObject(styleObj:Object):void {
			color = String(styleObj.color).substr(1) as uint;
			display = styleObj.display as String;
			fontFamily = styleObj.fontFamily as String;
			fontSize = styleObj.fontSize as int;
			fontWeight = styleObj.fontWeight;
			kerning = styleObj.kerning as Boolean;
			leading = styleObj.leading as int;
			letterSpacing = styleObj.letterSpacing as int;
			marginLeft = styleObj.marginLeft as int;
			marginRight = styleObj.marginRight as int;
			textAlign = styleObj.textAlign as String;
			textDecoration = styleObj.textDecoration as String;
			textIndent = styleObj.textIndent as int;
			blockIndent = styleObj.blockIndent as int;
			bullet = styleObj.bullet as Boolean;
			
			var tabStopsStr:String = styleObj.tabStops as String;
			if (tabStopsStr && tabStopsStr.length){
				tabStops = tabStopsStr.split(",");
				var i0:int = 0;
				var limit0:int = tabStops.length;
				for (; i0 < limit0 ; i0++) tabStops[i0] = parseInt(tabStops[i0]);
			}
		}
		
		public function getStyleObject():Object {
			var styleObject:Object = {
				name:_name ,
				display:display ,
				fontFamily:fontFamily ,
				fontSize:fontSize ,
				fontStyle:fontStyle ,
				fontWeight:fontWeight ,
				kerning:kerning ,
				leading:leading ,
				letterSpacing:letterSpacing ,
				marginLeft:marginLeft ,
				marginRight:marginRight ,
				textAlign:textAlign ,
				textDecoration:textDecoration ,
				textIndent:textIndent ,
				blockIndent:blockIndent ,
				bullet:bullet
			}
			
			if (color) styleObject.color = "#" + color.toString(16);
			if (tabStops) styleObject.tabStops = tabStops.join(", ");
			
			return styleObject;
		}
		
		public function placeInSheet (styleSheet:StyleSheet = null):StyleSheet {
			if (!styleSheet) styleSheet = new StyleSheet();
			styleSheet.setStyle(_name , getStyleObject());
			return styleSheet;
		}
		
		public function setToTextFormat (textFormat:TextFormat):void {
			color = textFormat.color;
			display = textFormat.display;
			fontFamily = textFormat.font;
			fontSize = textFormat.size;
			fontWeight = textFormat.bold ? "bold" : "none";
			kerning = textFormat.kerning;
			leading = textFormat.leading;
			letterSpacing = textFormat.letterSpacing;
			marginLeft = textFormat.leftMargin;
			marginRight = textFormat.rightMargin;
			textAlign = textFormat.align;
			textDecoration = textFormat.underline ? "underline" : "none";
			textIndent = textFormat.indent;
			blockIndent = textFormat.blockIndent;
			bullet = textFormat.bullet;
			tabStops = textFormat.tabStops;
			
			url = textFormat.url;
			target = textFormat.target;
		}
		
		public function getAsTextFormat ():TextFormat {
			var textFormat:TextFormat = new TextFormat(fontFamily , fontSize , color , fontWeight == "bold" , fontStyle == "italic" , textDecoration == "underline" , url , target , textAlign , marginLeft , marginRight , textIndent , leading);
			textFormat.display = display;
			textFormat.kerning = kerning;
			textFormat.letterSpacing = letterSpacing;
			textFormat.tabStops = tabStops;
			return textFormat;
		}
		
		public function parseStyleObject (styleObj:* , reset:Boolean = true):TextStyle {
			if (reset) resetToDefaults();
			
			if (styleObj.color is Object) {
				var colorStr:String = styleObj.color.toString();
				if (colorStr.charAt(0) == "#") colorStr = "0x" + colorStr.substr(1);
				if (styleObj.color is Object && !isNaN(parseFloat(colorStr))) color = parseInt(colorStr);
			}
			
			if (styleObj.display is Object && styleObj.display.toString().length) display = styleObj.display.toString();
			if (styleObj.fontFamily is Object && styleObj.fontFamily.text().length) fontFamily = styleObj.fontFamily.toString();
			if (styleObj.fontSize is Object && !isNaN(parseFloat(styleObj.fontSize.toString()))) fontSize = parseInt(styleObj.fontSize);
			if (styleObj.fontWeight is Object && styleObj.fontWeight.toString().length) fontWeight = styleObj.fontWeight.toString();
			if (styleObj.kerning is Object && styleObj.kerning.toString() == "true") kerning = true;
			if (styleObj.leading is Object && !isNaN(parseFloat(styleObj.leading.toString()))) leading = parseInt(styleObj.leading);
			if (styleObj.letterSpacing is Object && !isNaN(parseFloat(styleObj.letterSpacing.toString()))) letterSpacing = parseInt(styleObj.letterSpacing);
			if (styleObj.marginLeft is Object && !isNaN(parseFloat(styleObj.marginLeft.toString()))) marginLeft = parseInt(styleObj.marginLeft);
			if (styleObj.marginRight is Object && !isNaN(parseFloat(styleObj.marginRight.toString()))) marginRight = parseInt(styleObj.marginRight);
			if (styleObj.textAlign is Object && styleObj.textAlign.toString().length) textAlign = styleObj.textAlign.toString();
			if (styleObj.textDecoration is Object && styleObj.textDecoration.toString().length) textDecoration = styleObj.textDecoration.toString();
			if (styleObj.textIndent is Object && !isNaN(parseFloat(styleObj.textIndent.toString()))) textIndent = parseInt(styleObj.textIndent);
			if (styleObj.blockIndent is Object && !isNaN(parseFloat(styleObj.blockIndent.toString()))) blockIndent = parseInt(styleObj.blockIndent);
			if (styleObj.bullet is Object && styleObj.bullet.toString() == "true") bullet = true;
			
			if (styleObj.tabStops is Object && styleObj.tabStops.toString().length){
				tabStops = styleObj.tabStops is Array ? styleObj.tabStops : styleObj.tabStops.toString().split(",");
				var i0:int = 0;
				var limit0:int = tabStops.length;
				for (; i0 < limit0 ; i0++) tabStops[i0] = parseInt(tabStops[i0]);
			}
			
			return this;
		}
		
		public function getAsXML ():String {
			return "<styleObject>\n" +
	"<color>\n" + (color ? color.toString(16) : "") + "</color>\n" +
	"<display>\n" + display + "</display>\n" +
	"<fontFamily>\n" + fontFamily + "</fontFamily>\n" +
	"<fontSize>\n" + fontSize + "</fontSize>\n" +
	"<fontWeight>\n" + fontWeight + "</fontWeight>\n" +
	"<kerning>\n" + kerning + "</kerning>\n" +
	"<leading>\n" + leading + "</leading>\n" +
	"<letterSpacing>\n" + letterSpacing + "</letterSpacing>\n" +
	"<marginLeft>\n" + marginLeft + "</marginLeft>\n" +
	"<marginRight>\n" + marginRight + "</marginRight>\n" +
	"<textAlign>\n" + textAlign + "</textAlign>\n" +
	"<textDecoration>\n" + textDecoration + "</textDecoration>\n" +
	"<textIndent>\n" + textIndent + "</textIndent>\n" +
	"<blockIndent>\n" + blockIndent + "</blockIndent>\n" +
	"<bullet>\n" + bullet + "</bullet>\n" +
	"<tabStops>\n" + tabStops.join(","); + "</tabStops>\n" +
"</styleObject>";
		}
		
		/*public function getAsCSS ():String {
			
		}*/
		
		public function get name ():String { return _name; }
		public function set name (value:String):void {
			_name = value;
			if (_name != null && _name.charAt() != ".") trace("TextStyle: The first character of a style name must be '.' to be recognized in a stylesheet.");
		}
		
	}
	
}